package controller;

/*
 * Action for creating a new survey as a researcher.
 */

import formbeans.ImportEntityForm;
import helper.EntityAttributeType;
import helper.EntityType;
import helper.UserType;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.mybeans.dao.DAOException;
import org.mybeans.form.FormBeanException;
import org.mybeans.form.FormBeanFactory;

import databeans.Entity;
import databeans.EntityAttribute;
import databeans.EntityClass;
import databeans.Survey;
import databeans.User;
import model.EntityAttributeDAO;
import model.EntityClassDAO;
import model.EntityDAO;
import model.Model;
import model.SurveyDAO;

public class ImportEntityAction extends Action {
	private FormBeanFactory<ImportEntityForm> formBeanFactory = FormBeanFactory.getInstance(ImportEntityForm.class);
	private SurveyDAO surveyDAO;
	private EntityClassDAO ecDAO;
	private EntityDAO entityDAO;
	private EntityAttributeDAO eaDAO;
	
	public ImportEntityAction(Model model) {
		surveyDAO = model.getSurveyDAO();
		ecDAO = model.getEntityClassDAO();
		entityDAO = model.getEntityDAO();
		eaDAO = model.getEntityAttributeDAO();
	}
	
    public String getName() {
		return "importentity.do";
	}
    
    public String perform(HttpServletRequest request) {

        List<String> errors = new ArrayList<String>();
        request.setAttribute("errors",errors);
        
    	// First, validate whether researcher is accessing this
    	HttpSession session = request.getSession(false);
    	User user = (User) session.getAttribute("user");
    	
    	if (user.getType() != UserType.RESEARCHER) {
    		errors.add("You are not a researcher!");
    		return "homepage.jsp";
    	}
    	
    	// Validate the survey number
    	Survey survey = (Survey) session.getAttribute("survey");
    	
    	// Importing Entity Data file
    	if (request.getContentType() != null && request.getContentType().indexOf("multipart/form-data") >= 0) {
    		/*ServletContext sc = session.getServletContext();
    		String filePath = sc.getInitParameter("file-upload");*/
    		
    		DiskFileItemFactory factory = new DiskFileItemFactory();
    		factory.setSizeThreshold(512 * 1024 * 1024);
    		factory.setRepository(new File("C:\\temp"));
    		
    		ServletFileUpload upload = new ServletFileUpload(factory);
    		upload.setSizeMax(512 * 1024 * 1024);
    		
    		try {
    			@SuppressWarnings("unchecked")
				List<FileItem> fileitems = upload.parseRequest(request);
    			Iterator<FileItem> it = fileitems.iterator();
    			
    			while (it.hasNext()) {
    				FileItem fi = (FileItem)it.next();
    				if (!fi.isFormField()) {
    					String fieldName = fi.getFieldName();
    					String fileName = fi.getName();
    					boolean isInMemory = fi.isInMemory();
    					long sizeInBytes = fi.getSize();
    					
    					/*File file;
    					
    					if (fileName.lastIndexOf("\\") >= 0) {
    						file = new File(filePath + fileName.substring(fileName.lastIndexOf("\\")));
    					}
    					else {
    						file = new File(filePath + fileName.substring(fileName.lastIndexOf("\\") + 1));
    					}*/
    					
    					InputStream uploadedStream = fi.getInputStream();
    					
    					BufferedReader input = new BufferedReader(new InputStreamReader(uploadedStream));
    					Scanner scanner = new Scanner(input);
    					String[] attrNames = scanner.nextLine().split(",");
    					System.out.println("attrname length = " + attrNames.length);
    					
    					while (scanner.hasNextLine()) {
    						String[] entities = scanner.nextLine().split(",");
    						System.out.println("entites length = " + entities.length);
    						if (entities.length <= 0) {
    							throw new IllegalArgumentException("Error in file format, must have at least one column for id");
    						}
    						/*if (entities.length != attrNames.length && entities.length+1 != attrNames.length) { //Not the elegant solution, but a placeholder code to prevent a bug where if the end of line is comma, it doesn't get included in split array
    							throw new IllegalArgumentException("Error in file format, each row must have same number of columns");
    						}*/
    						
    						Entity entity = new Entity(entityDAO.getEid());
    						EntityClass ec = (EntityClass) session.getAttribute("entityclass");
    						entity.setEcid(ec.getEcid());
    						entity.setId(entities[0]);
    						
    						if (entities.length <= 1) // Set the name as equal to id if no name was specified
    							entity.setName(entities[0]);
    						else
    							entity.setName(entities[1]);
    						
    						entityDAO.create(entity, ecDAO);
    						
    						if (entities.length > 2) { // There are some attributes to this entity
    							for (int i = 2; i < entities.length; i++) {
    								if (entities[i].length() > 0) {
	    								EntityAttribute ea = new EntityAttribute(entity.getEid(), attrNames[i]);
	    								ea.setValue(entities[i]);
	    								ea.setAttrtype(EntityAttributeType.TEXT);
	    								eaDAO.create(ea, entityDAO);
    								}
    							}
    						}
    					}
    					
    					input.close();
    					uploadedStream.close();
    					
    					EntityClass ec = (EntityClass) session.getAttribute("entityclass");
    					Entity[] entitylist = entityDAO.getEntityByEcid(ec.getEcid());
    					
    					synchronized(session) {
    						session.setAttribute("importentitybody", "complete");
    						session.setAttribute("importentitydata", entitylist);
    					}
    					
    					System.out.println("fieldName = " + fieldName + "\nfileName = " + fileName + "\nisInMemory = " + isInMemory + "\nsizeInBytes = " + sizeInBytes);
    				}
    			}
    		} catch (FileUploadException e) {
    			errors.add(e.getMessage());
    			return "createsurvey.jsp";
    		} catch (IllegalArgumentException e) {
    			errors.add(e.getMessage());
    			return "createsurvey.jsp";
    		} catch (Exception e) {
    			errors.add(e.getMessage());
    			return "createsurvey.jsp";
    		}
    		
    		return "importentity.jsp";
    	}
    	
		String button = request.getParameter("button");
		
		if (button == null)
			return "importentity.jsp";
		
		if (button.equals("Back") || button.equals("Ok")) {
			String from = (String) session.getAttribute("pageFrom");
			try {
				EntityClass[] ec = ecDAO.getEntityClassBySid(survey.getSid());
				
				synchronized(session) {
					session.removeAttribute("importentitydata");
					session.removeAttribute("importentitybody");
					session.removeAttribute("pageFrom");
					session.setAttribute("entityclass", ec);
				}
			} catch (DAOException e) {
				errors.add(e.getMessage());
	        	return "errors.jsp";
			}
			
			return from;
		}
		
		if (button.equals("Next")) {
			try {
				ImportEntityForm form = formBeanFactory.create(request);
            	request.setAttribute("importentityform",form);
            	
            	if (!form.isPresent()) {
            		return "importentity.jsp";
            	}
            	
        		// Validate for errors in the form
        		errors.addAll(form.checkImportEntityFormErrors());
        		if (errors.size() != 0) {
        			return "importentity.jsp";
        		}
        		
        		EntityClass ec = new EntityClass(ecDAO.getEcid());
        		ec.setName(form.getClassName());
        		ec.setSid(survey.getSid());
        		
        		if (form.getType().equals("Agent"))
        			ec.setType(EntityType.AGENT);
        		else if (form.getType().equals("Organization"))
        			ec.setType(EntityType.ORGANIZATION);
        		else if (form.getType().equals("Knowledge"))
        			ec.setType(EntityType.KNOWLEDGE);
        		else if (form.getType().equals("Resource"))
        			ec.setType(EntityType.RESOURCE);
        		else if (form.getType().equals("Belief"))
        			ec.setType(EntityType.BELIEF);
        		else if (form.getType().equals("Event"))
        			ec.setType(EntityType.EVENT);
        		else if (form.getType().equals("Task"))
        			ec.setType(EntityType.TASK);
        		else if (form.getType().equals("Location"))
        			ec.setType(EntityType.LOCATION);
        		else if (form.getType().equals("Role"))
        			ec.setType(EntityType.ROLE);
        		else if (form.getType().equals("Action"))
        			ec.setType(EntityType.ACTION);
        		
        		ecDAO.create(ec, surveyDAO);
        		synchronized(session) {
        			session.setAttribute("entityclass", ec);
        			session.setAttribute("importentitybody", "import");
        		}
        		
        		return "importentity.jsp";
			} catch (DAOException e) {
	        	errors.add(e.getMessage());
	        	return "errors.jsp";
	        } catch (FormBeanException e) {
	        	errors.add(e.getMessage());
	        	return "errors.jsp";
	        } 
		}
		
		errors.add("Illegal button value of " + button);
		return "errors.jsp";
    }
}
